import os
import random

import cv2
import exifread
from PIL import Image
from flask import Blueprint, send_file, request

from config.load_yaml import load_config
from flask_moudle.classes.ResultMap import ResultMap
from .upload_file_bp import dms_to_degrees
from ..service.image_analysis import get_amap_coordinate, get_regeo_address, add_text_to_image
from ..service.predict import instance_seg_predict, seg_predict

analysis_bp = Blueprint('analysis_bp', __name__)

config = load_config()
origin_path = config['path']['origin_path']
predict_path = config['path']['predict_path']
model_path = config['path']['model_path']
http_methods = ['GET', 'POST']
camera = (1691, 2.41, 8.8)


def photo_to_fact(height: 1691, pixel_size: 2.41, f: 8.8) -> float:
    """
    计算照片中每一个像素点的实际大小
    :param height: 无人机飞行高度 m
    :param pixel_size: 像元大小 微米 um
    :param f: 焦段 mm
    :return: 每个像素点边长 cm
    """
    return height * pixel_size / (10 * f)


def parse_args(requests, post_type='form'):
    """

    :param requests: http request
    :param post_type: eg. form or json
    :return: dict()
    """
    if requests.method == 'GET':
        return requests.args
    elif requests.method == 'POST':
        # 获取POST请求的参数
        if post_type == 'form':
            return requests.form
        else:
            return requests.json


@analysis_bp.route('/predict/<img_name>', methods=http_methods, endpoint='predict_img')
def predict_img(img_name):
    """

    :type img_name: file_path
    :rtype: object
    """
    # print(parse_args(requests=request, post_type='json'))
    args = parse_args(requests=request, post_type='json')
    image = Image.open(os.path.join(origin_path, img_name))
    print(args)
    blend_image, mask_image, analysis = instance_seg_predict(image, model=args.get('model', 'yolov8-seg'),
                                                             conf=args.get('conf', 0.25),
                                                             iou=args.get('iou', 0.5),
                                                             blend=args.get('blend', 0.7),
                                                             imgsz=args.get('imgsz', [1024, 1024]),
                                                             classes=args.get('classes',
                                                                              ['intact', 'slight', 'severe',
                                                                               'collapse']),
                                                             show_bbox=args.get('show_bbox', False),
                                                             show_labels=args.get('show_labels', False),
                                                             show_conf=args.get('show_conf', False)
                                                             )
    # 生成四位随机数
    random_number = ''.join(random.choices('0123456789', k=4))
    name = img_name.split('.')[0] + '_' + random_number + '_predict.' + img_name.split('.')[1]
    blend_image.save(os.path.join(predict_path, name))
    with open(origin_path + '/' + img_name, 'rb') as file:
        tags = exifread.process_file(file)
        if tags != {}:
            longitude = tuple(tags['GPS GPSLongitude'].values)
            latitude = tuple(tags['GPS GPSLatitude'].values)
            information = {
                'longitude': dms_to_degrees(*longitude),
                'latitude': dms_to_degrees(*latitude),
                'altitude': float(tags['GPS GPSAltitude'].values[0]),
                'time': tags['Image DateTime'].values,
                'analysis': analysis,
                'location': get_regeo_address(
                    get_amap_coordinate(f'{dms_to_degrees(*longitude)},{dms_to_degrees(*latitude)}')).get(
                    "formatted_address", None)
            }
            add_text_to_image(os.path.join(predict_path, name), information['location'],
                              os.path.join(predict_path, name))
        else:
            information = {
                'longitude': '',
                'latitude': '',
                'altitude': '',
                'time': '',
                'analysis': analysis,
                'location': ''
            }
    information['analysis'] = analysis
    url = ['/predict_preview/' + name, '/origin_preview/' + img_name, 'https://file.zouran.top/imgs/fenxi/legend.png']
    # analysis = {key: analysis[key] * ((photo_to_fact(*camera) / 100) ** 2) for key in analysis.keys()}
    return ResultMap().success_message_data('识别成功', {'url': url, 'information': information})


@analysis_bp.route('/crack_predict/<img_name>', methods=http_methods)
def crack_predict_img(img_name):
    result = seg_predict(os.path.join(origin_path, img_name))
    with open(origin_path + '/' + img_name, 'rb') as file:
        tags = exifread.process_file(file)
        if tags != {}:
            longitude = tuple(tags['GPS GPSLongitude'].values)
            latitude = tuple(tags['GPS GPSLatitude'].values)
            information = {
                'longitude': dms_to_degrees(*longitude),
                'latitude': dms_to_degrees(*latitude),
                'altitude': None,
                'time': tags.get('Image DateTime', None),
                'location': get_regeo_address(
                    get_amap_coordinate(f'{dms_to_degrees(*longitude)},{dms_to_degrees(*latitude)}')).get(
                    "formatted_address", None)
            }
        else:
            information = {
                'longitude': '',
                'latitude': '',
                'altitude': '',
                'time': '',
                'location': ''
            }
    name = img_name.split('.')[0] + '_predict.' + img_name.split('.')[1]
    cv2.imwrite(os.path.join(predict_path, name), result)
    url = {
        'origin': f'/origin_preview/{img_name}',
        'predict': f'/predict_preview/{name}'
    }
    return ResultMap().success_message_data('识别成功', {'url': url, 'information': information})


@analysis_bp.route('/predict_preview/<img_name>', methods=http_methods)
def show_img(img_name):
    """

    :param img_name: 文件名
    :return: 图片
    """
    img_path = os.path.join(predict_path, img_name)
    return send_file(img_path, mimetype='image/png')


@analysis_bp.route('/origin_preview/<img_name>', methods=http_methods)
def show_origin_img(img_name):
    """

    :param img_name: 文件名
    :return: 图片
    """
    img_path = os.path.join(origin_path, img_name)
    return send_file(img_path, mimetype='image/png')
